<!DOCTYPE HTML>
<html>
<head>
<title>重映射按键(键盘, 鼠标和操纵杆) | AutoHotkey</title>
<meta name="description" content="也能重映射鼠标和操纵杆按钮的免费键盘重映射工具它还可以通过发送键盘键击和鼠标点击来自动化重复的任务.">
<meta name="keywords" content="keyboard,remapper,remap,remapping,keys,key,keystrokes,clicks,mouse,buttons,button,joystick,hotkeys,hotkey">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link href="../static/theme.css" rel="stylesheet" type="text/css" />
<script src="../static/content.js" type="text/javascript"></script>
</head>
<body>

<h1>重映射按键 <span class="headnote">(键盘, 鼠标和操纵杆)</span></h1>

<h2 id="toc">目录</h2>
<ul>
  <li><a href="#intro">简介</a></li>
  <li><a href="#Remap">重映射键盘和鼠标</a></li>
  <li><a href="#remarks">备注</a></li>
  <li><a href="#moving-the-mouse-cursor">通过键盘移动鼠标光标</a></li>
  <li><a href="#registry">使用注册表的 "扫描码映射" 功能进行重映射</a></li>
  <li><a href="#related">相关话题</a></li>
</ul>

<h2 id="intro">简介</h2>
<p><strong>限制</strong>: 下面描述的 AutoHotkey 重映射功能通常不如直接通过 Windows 注册表进行映射那么直接有效. 对于每种方法的优点和缺点, 请参阅<a href="#registry">注册表重映射</a>.</p>
<h2 id="Remap">重映射键盘和鼠标</h2>
<p>内置重映射功能的语法为 <code>OriginKey::DestinationKey</code>. 例如, 只包含下面这行内容的<a href="../Scripts.htm">脚本</a>会将 <kbd>A</kbd> 重映射成 <kbd>B</kbd>:</p>
<pre>a::b</pre>
<p>上面的例子没有改变 <kbd>B</kbd> 自身的功能. <kbd>B</kbd> 会继续发送 "b" 的键击, 除非把它重映射成其他功能, 就像下面例子中演示的那样:</p>
<pre>a::b
b::a</pre>
<p>上述例子中使用小写字母, 在大多数情况下建议这么做, 因为它也会映射相应的大写字母(即在 <kbd>CapsLock</kbd> 打开或 <kbd>Shift</kbd> 被按住时会发送大写形式). 与之相比, 在右边使用大写字母会强制发送大写形式. 例如, 下面的代码行在您输入 "a" 或 "A" 时都会产生大写字母 B(只要 <kbd>CapsLock</kbd> 是关闭的):</p>
<pre>a::B</pre>
<p id="blind-pitfall">然而, 与上面相反的映射将不会像人们所期望的那样工作, 因为一个重新映射从来不会 "释放" 用来触发它的修饰符键. 例如, <code>A::b</code> 通常相当于 <code>A::B</code> 和 <code>^a::b</code> 相当于 <code>^a::^b</code>. 这是因为每个重映射<a href="#actually">在内部使用 {Blind}</a> 来允许键或键组合与其他修饰符组合在一起.</p>

<h3 id="RemapMouse">鼠标重映射</h3>
<p>要映射鼠标为键盘, 请使用和映射键盘相同的方法. 例如:</p>
<table class="info">
  <tr>
    <th style="min-width: 12em;">示例</th>
    <th abbr="Descr">描述</th>
  </tr>
  <tr>
    <td><code>MButton::Shift</code></td>
    <td>把鼠标中键映射成 <kbd>Shift</kbd>.</td>
  </tr>
  <tr>
    <td><code>XButton1::LButton</code></td>
    <td>把第四个鼠标按钮映射成鼠标左键.</td>
  </tr>
  <tr>
    <td><code>RAlt::RButton</code></td>
    <td>把右 <kbd>Alt</kbd> 映射成鼠标右键.</td>
  </tr>
</table>

<h3 id="other-useful-remappings">其他有用的映射</h3>
<table class="info">
  <tr>
    <th style="min-width: 12em;">示例</th>
    <th abbr="Descr">描述</th>
  </tr>
    <td><code>CapsLock::Ctrl</code></td>
    <td>把 <kbd>CapsLock</kbd> 映射成 <kbd>Ctrl</kbd>. 要保留打开及关闭 <kbd>CapsLock</kbd> 的功能, 需先包含重映射 <code>+CapsLock::CapsLock</code>. 这样, 当按住 <kbd>Shift</kbd> 并点击 Capslock 时, 可切换 <kbd>CpasLock</kbd> 的开关状态. 因为两个重映射均允许附加修饰键被按下, 额外指定的 <code>+CapsLock::CapsLock</code> 重映射须优先放置.</td>
  </tr>
  <tr>
    <td><code>XButton2::^LButton</code></td>
    <td>把第五个鼠标按钮(XButton2) 映射成 Control-LeftClick.</td>
  </tr>
  <tr>
    <td><code>RAlt::AppsKey</code></td>
    <td>把右 <kbd>Alt</kbd> 映射成 <kbd>Menu</kbd>(这是打开上下文菜单的按键).</td>
  </tr>
  <tr>
    <td><code>RCtrl::RWin</code></td>
    <td>把右 <kbd>Ctrl</kbd> 映射成右 <kbd>Win</kbd>.</td>
  </tr>
  <tr>
    <td><code>Ctrl::Alt</code></td>
    <td>把左右 <kbd>Ctrl</kbd> 映射成 <kbd>Alt</kbd>. 但是, 请参阅 <a href="#AltTab">alt-tab 的问题</a>.</td>
  </tr>
  <tr>
    <td><code>^x::^c</code></td>
    <td>把 <kbd>Ctrl</kbd>+<kbd>X</kbd> 映射成 <kbd>Ctrl</kbd>+<kbd>C</kbd>. 它也会让 <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>X</kbd> 产生 <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>C</kbd>, 等等.</td>
  </tr>
  <tr>
    <td></code>RWin::Return</code></td>
    <td>禁用右 <kbd>Win</kbd>, 通过简单地执行 <a href="../lib/Return.htm">return</a>.</td>
  </tr>
</table>
<p>您可以尝试执行这里的每个例子: 把它们复制到新文本文件(例如 "Remap.ahk"), 然后运行这个文件.</p>
<p>请参阅<a href="../KeyList.htm">按键列表</a>来了解按键和鼠标按钮名称的完整列表.</p>
<h2 id="remarks">备注</h2>
<p>使用 <a href="../lib/_IfWinActive.htm">#IfWinActive/Exist</a> 指令可以让重映射仅在指定的窗口中有效. 例如:</p>
<pre>#IfWinActive ahk_class Notepad
a::b  <em>; 让 'a' 键到 'b' 键的映射仅在记事本中有效.</em>
#IfWinActive  <em>; 这里让后续的重映射和热键对所有窗口生效.</em></pre>
<p>重映射按键和鼠标按钮在下面的关系中是 "完整的":</p>
<ul>
  <li>按住修饰符(例如 <kbd>Ctrl</kbd> 或 <kbd>Shift</kbd>) 后按下原始键, 会让那个修饰符对目标键生效. 例如, <code>b::a</code> 会在您按下 <kbd>Ctrl</kbd>+<kbd>B</kbd> 时产生 <kbd>Ctrl</kbd>+<kbd>A</kbd> 的效果.</li>
  <li><kbd>CapsLock</kbd> 通常会像普通键那样影响重映射的按键.</li>
  <li>按住目标键或按钮的时间和您持续按住原始键的时间一样长. 但是, 一些游戏不支持重映射; 此时, 键盘和鼠标的重映射没有效果.</li>
  <li>按住被重映射的按键时, 它们的目标键会自动重复(除非是把按键重映射为鼠标按钮).</li>
</ul>
<p id="HookHotkeys">尽管被重映射的按键可以触发普通热键, 但默认情况下它不能触发鼠标热键或<a href="../lib/_UseHook.htm">钩子热键</a>(请使用 <a href="../lib/ListHotkeys.htm">ListHotkeys</a> 来找出哪些热键使用了钩子). 例如, 如果重映射 <code>a::b</code> 有效, 那么按下 <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>A</kbd> 会触发 <code>^!b</code> 热键, 但仅在 <code>^!b</code> 不是钩子热键的时候. 如果 <code>^!b</code> 是钩子热键, 而且您希望使用 <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>A</kbd> 来执行和 <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>B</kbd> 相同的动作, 那么您可以把 <code>^!a</code> 定义为热键. 例如:</p>
<pre>a::b
^!a::
^!b::
ToolTip You pressed %A_ThisHotkey%.
return</pre>
<p>在 <span class="ver">[v1.1.06]</span>  及更高版本中, 还可使用 <a href="../lib/_InputLevel.htm">#InputLevel</a> 来覆盖此默认行为. 例如:</p>
<pre>#InputLevel 1
a::b

#InputLevel 0
^!b::
ToolTip You pressed %A_ThisHotkey%.
return</pre>
<p id="SendPlay">如果在自动运行段(脚本的顶部) 使用了 <a href="../lib/SendMode.htm">SendMode</a>, 那么它会影响所有的重映射. 但是, 由于重映射使用 <a href="../lib/Send.htm#blind">Send {Blind}</a> 而 <a href="../lib/SendMode.htm">SendPlay 模式</a>不完全支持 {Blind}, 所以一些映射在 SendPlay 模式中可能无法正常运行(尤其是 <kbd>Ctrl</kbd>, <kbd>Shift</kbd>, <kbd>Alt</kbd> 和 <kbd>Win</kbd>). 要变通解决此问题, 当您脚本中含有重映射时请避免在自动执行段中使用 SendPlay; 而仅在整个脚本的一些需要的地方使用 <a href="../lib/Send.htm#SendPlay">SendPlay</a> 命令而不是 Send. 或者, 您可以把您的重映射转换为热键(如下所述), 这样就明确调用 SendEvent 而不是 Send.</p>
<p id="actually">加载脚本时, 每个重映射会被转换为一对<a href="../Hotkeys.htm">热键</a>. 例如, 包含重映射 <code>a::b</code> 的脚本实际包含下面的两个热键:</p>
<pre>*<strong>a</strong>::
SetKeyDelay -1   <em>; 如果目标键是鼠标按钮, 则使用 SetMouseDelay 代替.</em>
Send <a href="../lib/Send.htm#blind">{Blind}</a>{<strong>b</strong> DownR}  <em>; <a href="../lib/Send.htm#DownR">DownR</a> 和 Down 相似, 不过使用 DownTemp 时脚本中后面的其他 Send 命令则不会假定 "b" 仍然处于按下的状态.</em>
return

*<strong>a up</strong>::
SetKeyDelay -1  <em>; 请参阅下面的注意事项来了解在这段代码中两处 SetKeyDelay 都没有指定按键时长的原因.</em>
Send {Blind}{<strong>b</strong> up}
return</pre>
<p>但是, 上面的两个热键在下列环境中会发生变化:</p>
<ol>
  <li>当原始键为左 <kbd>Ctrl</kbd> 而目标键为 <kbd>Alt</kbd> 时, 会把 <code>Send {Blind}{LAlt DownR}</code> 这行语句替换为 <code>Send {Blind}<strong>{LCtrl up}</strong>{LAlt DownR}</code>. 如果原始键为右 <kbd>Ctrl</kbd> 也会如此, 除非使用了 <code>{RCtrl up}</code>.</li>
  <li>当键盘按键被重映射为鼠标按钮时(例如 <code>RCtrl::RButton</code>), 在上面的热键中会使用 SetMouseDelay 代替 SetKeyDelay. 而且, 上面的首个热键会被替换为下面的热键, 这样避免了由于键盘的自动重复功能生成的重复的鼠标点击:
    <pre>*RCtrl::
SetMouseDelay -1
if not GetKeyState("RButton")  <em>; 即鼠标右键还没有按下.</em>
    Send {Blind}{RButton DownR}
return</pre>
  </li>
  <li>当源代码是 <span class="ver">[v1.1.27.01+]</span> 中的自定义组合键时, 通配符修饰符(*) 被省略以允许热键工作.</li>
</ol>
<p>在 <span class="ver">[v1.1.27]</span> 之前, 使用 <a href="../lib/Send.htm#DownTemp">DownTemp</a> 而不是 <a href="../lib/Send.htm#DownR">DownR</a>.</p>
<p>请注意在上面的热键中省略了 SetKeyDelay 的第二个参数(<a href="../lib/SetKeyDelay.htm#dur">按键时长</a>). 这是因为按键时长不适用于独立的按键按下或按键弹起事件, 例如 <code>{b down}</code> 和 <code>{b up}</code>. 但是, 它适用于修饰键(Shift, Ctrl, Alt 和 Win) 状态的改变, 这会影响像 <code>a::B</code> 或 <code>a::^b</code> 的重映射. 因此, 脚本中任何在<a href="../Scripts.htm#auto">自动执行段</a>生效的按键时长会应用于所有这类重映射.</p>
<p>由于重映射会被简单翻译为上面描述的热键, 所以 <a href="../lib/Suspend.htm">Suspend</a> 也会影响它们. 同样地, <a href="../lib/Hotkey.htm">Hotkey</a> 命令可以禁用或修改重映射. 例如, 下面的两个命令会禁用重映射 <code>a::b</code>.</p>
<pre>Hotkey, *a, Off
Hotkey, *a up, Off</pre>
<p id="AltTab">Alt-tab 的问题: 如果您把一个按键或鼠标按钮映射为 <kbd>Alt</kbd>, 那么这个键很可能无法正确实现 alt-tab 的功能. 一个可能的变通解决方法是添加热键 <code>*Tab::Send {Blind}{Tab}</code>, 但是需要注意这样很可能妨碍使用真正的 <kbd>Alt</kbd> 实现 alt-tab 的功能. 因此, 这种方法只应当用于在您希望单独使用重映射的按键和/或 <a href="../Hotkeys.htm#alttab">alt-tab 热键</a>实现 alt-tab 功能的时候.</p>
<p>除了<a href="../KeyList.htm">按键列表</a>页面中的按键和鼠标按钮, 原始键还可以是在<a href="../KeyList.htm#SpecialKeys">特殊按键</a>页面描述的虚拟键(VKnn) 或扫描码(SCnnn). 对于目标键同样如此, 不过它还可以在虚拟键后指定扫描码. 例如, 在大多数键盘布局中 <code>sc01e::vk42sc030</code> 相当于 <code>a::b</code>.</p>
<p>要禁用按键而不进行重映射, 请把它设置为只含有 <a href="../lib/Return.htm">return</a> 的热键. 例如,<code>F1::return</code> 会禁用 <kbd>F1</kbd>.</p>
<p>内置的重映射功能不支持下列键:</p>
<ul>
  <li>鼠标滚轮(WheelUp/Down/Left/Right).</li>
  <li>Pause 和 Break 不能作为目标键(因为它们会被作为命令执行).</li>
  <li>大括号 {} 不能作为目标键. 作为替代请使用 <a href="../lib/Send.htm#vk">VK/SC 方法</a>; 例如 <code>x::+sc01A</code> 和 <code>y::+sc01B</code>.</li>
  <li>百分号(%) 不能作为目标键. 作为替代请使用 <a href="../lib/Send.htm#vk">VK/SC 方法</a>.</li>
  <li>"Return" 不能作为目标键. 作为替代请使用 "Enter".</li>
</ul>
<h2 id="moving-the-mouse-cursor">通过键盘移动鼠标光标</h2>
<p>如同在全功能<a href="../scripts/NumpadMouse.htm">键盘到鼠标的映射脚本</a>中演示的那样, 可以使用键盘来移动鼠标光标. 由于这个脚本提供了鼠标平滑移动, 加速和其他功能, 所以如果您想使用键盘实现许多的鼠标操作, 推荐您使用这个脚本. 与之相比, 下面的例子只是简化的演示:</p>
<pre>*#up::MouseMove, 0, -10, 0, R  <em>; Win+UpArrow 热键 =&gt; 上移光标</em>
*#Down::MouseMove, 0, 10, 0, R  <em>; Win+DownArrow =&gt; 下移光标</em>
*#Left::MouseMove, -10, 0, 0, R  <em>; Win+LeftArrow =&gt; 左移光标</em>
*#Right::MouseMove, 10, 0, 0, R  <em>; Win+RightArrow =&gt; 右移光标</em>

*&lt;#RCtrl::  <em>; LeftWin + RightControl =&gt; Left-click (按住 Control/Shift 来进行 Control-Click 或 Shift-Click).</em>
SendEvent {Blind}{LButton down}
KeyWait RCtrl  <em>; 防止键盘自动重复导致的重复鼠标点击.</em>
SendEvent {Blind}{LButton up}
return

*&lt;#AppsKey::  <em>; LeftWin + AppsKey =&gt; Right-click</em>
SendEvent {Blind}{RButton down}
KeyWait AppsKey  <em>; 防止键盘自动重复导致重复的鼠标点击.</em>
SendEvent {Blind}{RButton up}
return</pre>
<h2 id="registry">使用注册表的 "扫描码映射" 功能进行重映射</h2>
<p><strong>优点:</strong></p>
<ul>
  <li>注册表的重映射功能通常比 <a href="#Remap">AutoHotkey 的重映射</a>更加直接有效. 例如, 它能适应于更大范围的游戏, 它不存在 <a href="#AltTab">alt-tab 问题</a>, 并且它能触发 AutoHotkey 的钩子热键(然而 AutoHotkey 的重映射需要<a href="#HookHotkeys">间接的方法</a>才行).</li>
  <li>如果您会手动修改注册表条目(下面进行阐述), 那么不需要任何外部软件就可以重映射您的键盘. 即使您使用 <a href="https://www.bleepingcomputer.com/download/keytweak/">KeyTweak</a> 来修改注册表条目, 那么完成后 KeyTweak 不需要一直保持运行(而 AutoHotkey 需要一直运行, 重映射才会生效).</li>
</ul>
<p><strong>缺点:</strong></p>
<ul>
  <li>注册表重映射比较不灵活: 每次修改映射都必须重启后才会生效.</li>
  <li>效果是全局的: 它不能创建针对特定用户, 应用程序或环境的重映射.</li>
  <li>它无法发送含修饰键 <kbd>Shift</kbd>, <kbd>Ctrl</kbd>, <kbd>Alt</kbd> 或 <kbd>AltGr</kbd> 的组合键. 例如, 它不能把小写字符映射为大写字符.</li>
  <li>它只支持键盘(AutoHotkey 还支持<a href="#RemapMouse">鼠标重映射</a>和一些<a href="RemapJoystick.htm">受限的操纵杆重映射</a>).</li>
</ul>
<p><strong>如何修改注册表:</strong> 使用注册表重映射按键至少有两种方法:</p>
<ol>
  <li>使用像 <a href="https://www.bleepingcomputer.com/download/keytweak/">KeyTweak</a>(免费软件) 这样的程序在可视界面中重映射按键. 它会自动修改注册表.</li>
  <li>手动创建重映射按键的 .reg 文件(纯文本) 并把它载入注册表. 演示的例子请参阅<a href="https://www.autohotkey.com/board/index.php?showtopic=8359#entry52760">旧的论坛帖子</a>.</li>
</ol>
<h2 id="related">相关主题</h2>
<ul>
  <li><a href="../KeyList.htm#Joystick">按键和鼠标按钮列表</a></li>
  <li><a href="../lib/GetKeyState.htm#function">GetKeyState()</a></li>
   <li><a href="RemapJoystick.htm">重映射操纵杆</a></p></li>
 </ul>
</body>
</html>